import { forwardRef, Inject, Injectable } from '@nestjs/common';
import { TenantEntity } from './tenant.entity';
import { Like, Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { CommonStatus } from '~/common/entity/common.entity';
import { generateRandomValue } from '~/utils/tool.util';
import { BusinessException } from '~/common/exceptions/biz.exception';
import { ErrorEnum } from '~/constants/error-code.constant';
import { isNil } from 'lodash';
import { UserService } from '../user/user.service';
import { FindTenantListDto } from './tenant.dto';
import { Pagination } from '~/helper/paginate/pagination';
import { paginate } from '~/helper/paginate';

@Injectable()
export class TenantService {
  constructor(
    @InjectRepository(TenantEntity)
    private readonly tenantRepo: Repository<TenantEntity>,
    @Inject(forwardRef(() => UserService))
    private readonly userService: UserService
  ) {}

  /**
   * 创建租户
   */
  async createTenant(tenant: Partial<TenantEntity>): Promise<TenantEntity> {
    // 生成租户编码
    tenant.code = generateRandomValue(20);
    return await this.tenantRepo.save(tenant);
  }

  /**
   * 更新租户信息
   */
  async updateTenant(id: number, tenant: Partial<TenantEntity>): Promise<TenantEntity> {
    // 检查租户是否存在
    const existingTenant = await this.getTenantById(id);
    if (!existingTenant) {
      throw new BusinessException(ErrorEnum.NO_TENANT);
    }

    // 更新租户信息
    await this.tenantRepo.update(id, tenant);

    // 返回更新后的租户信息
    return await this.getTenantById(id);
  }

  /**
   * 删除租户
   */
  async deleteTenant(id: number): Promise<void> {
    if (id === 1) {
      throw new BusinessException(ErrorEnum.TENANT_CANNOT_DELETE);
    }

    const tenant = await this.getTenantById(id);

    if (!tenant) {
      throw new BusinessException(ErrorEnum.NO_TENANT);
    }

    const hasUser = await this.userService.hasUserBindTenant(id);

    if (hasUser) {
      throw new BusinessException(ErrorEnum.TENANT_HAS_USER);
    }

    // 软删除：将状态设置为禁用
    await this.tenantRepo.update(id, { status: CommonStatus.NO });
  }

  /**
   * 恢复租户
   */
  async restoreTenant(id: number): Promise<void> {
    const tenant = await this.getTenantByIdIncludeDeleted(id);

    if (!tenant) {
      throw new BusinessException(ErrorEnum.NO_TENANT);
    }

    // 检查租户是否已经是启用状态
    if (tenant.status === CommonStatus.YES) {
      throw new BusinessException(ErrorEnum.TENANT_ALREADY_ENABLED);
    }

    // 恢复：将状态设置为启用
    await this.tenantRepo.update(id, { status: CommonStatus.YES });
  }

  /**
   * 获取所有租户信息
   */
  async getAllTenants(name?: string): Promise<TenantEntity[]> {
    // 查找所有状态为启用的租户
    return await this.tenantRepo.find({
      where: { status: CommonStatus.YES, ...(!isNil(name) ? { name: Like(`%${name}%`) } : {}) },
    });
  }

  /**
   * 获取所有租户信息（包括已删除的）
   */
  async getAllTenantsIncludeDeleted(): Promise<TenantEntity[]> {
    // 查找所有租户，包括已删除的
    return await this.tenantRepo.find();
  }

  /**
   * 获取租户信息 - 租户ID
   */
  async getTenantById(id: number): Promise<TenantEntity> {
    return await this.tenantRepo.findOneBy({ id });
  }

  /**
   * 获取租户信息 - 租户ID（包含已删除的）
   */
  async getTenantByIdIncludeDeleted(id: number): Promise<TenantEntity> {
    return await this.tenantRepo.findOneBy({ id });
  }

  /**
   * 判断租户是否存在
   */
  async hasTenant(id: number): Promise<boolean> {
    const tenant = await this.getTenantById(id);

    if (isNil(tenant)) {
      return false;
    }

    return true;
  }

  /**
   * 获取租户信息 - 租户编码
   */
  async getTenantByCode(code?: string): Promise<TenantEntity> {
    if (!code) {
      return null;
    }

    return await this.tenantRepo.findOneBy({ code });
  }

  async bindTenant(userId: number, tenantId: number): Promise<void> {
    const tenant = await this.getTenantById(tenantId);

    if (isNil(tenant)) {
      throw new BusinessException(ErrorEnum.NO_TENANT);
    }

    await this.userService.bindAdminToTenant(userId, tenant);
  }

  async findTenantsByList({
    page,
    pageSize,
    name,
    status,
    code,
  }: FindTenantListDto): Promise<Pagination<TenantEntity>> {
    const queryBuilder = this.tenantRepo
      .createQueryBuilder('ah_tenant')
      .leftJoinAndSelect('ah_tenant.admin', 'admin')
      .where({
        ...(!isNil(name) ? { name: Like(`%${name}%`) } : {}),
        ...(!isNil(code) ? { code: Like(`%${code}%`) } : {}),
        ...(!isNil(status) ? { status } : { status: CommonStatus.YES }), // 默认只查询启用状态的租户
      });

    return paginate<TenantEntity>(queryBuilder, {
      page,
      pageSize,
    });
  }
}
